import track, { resetTrack, pauseTrack } from "../../effect/track.js";
import { TrackOpTypes, isObject, RAW } from "../../utils.js";
import { reactive } from "../../reactive.js";

// 对数组中的查找方法重写
const arrayInstrumentations = {};

["includes", "indexOf", "lastIndexOf"].forEach((key) => {
  arrayInstrumentations[key] = function (...args) {
    // 1.先正常找
    const res = Array.prototype[key].apply(this, args);
    // 2. 如果找不到
    if (res < 0 || res === false) {
      // 这里就需要拦截器返回原始的对象
      // this[RAW] 拿到的就是原始对象
      return Array.prototype[key].apply(this[RAW], args);
    }

    return res;
  };
});

// 如果是数组的push,unshift, pop, shift, splice方法，则我们并不需要对数组的length进行依赖收集
["push", "unshift", "pop", "shift", "splice"].forEach((key) => {
  arrayInstrumentations[key] = function (...args) {
    pauseTrack();
    const res = Array.prototype[key].apply(this, args);
    resetTrack();
    return res;
  };
});

/**
 * 数据读取
 * @param {*} target 元素对象
 * @param {*} key  属性
 * @returns
 */
export default function (target, key) {
  // 如果是数组，并且是数组的查找方法，则直接返回原始对象
  if (key === RAW) {
    return target;
  }

  track(target, TrackOpTypes.GET, key);

  // 如果是数组的某些方法，则需要对其进行改写
  if (arrayInstrumentations[key] && Array.isArray(target)) {
    return arrayInstrumentations[key];
  }

  // 需要判断获取的属性是否为一个对象
  const result = Reflect.get(target, key);

  // 如果是一个数组的查找操作，并且数组中存在对象，则需要返回原始对象

  if (isObject(result)) {
    // 如果是一个对象，则需要对其进行递归处理，将其转换成一个响应式对象
    return reactive(result);
  }
  return result;
}
